﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using WeddingEventManagement_API;
using WeddingEventManagementApp.Models;

namespace WeddingEventManagementApp.Controllers
{
    public class EventController : BaseController
    {
        IEventManager eventManager;

        // Default constructor
        public EventController()
        {
            eventManager = new EventManager();
        }

        //
        // GET: /Event/

        public ActionResult Index()
        {
            var model = new EventMain_VM
            {
                UpcomingEvents = eventManager.GetUpcomingEvents(5),
                RecentAddedEvents = eventManager.GetMostRecentlyAddedEvents(5),
                RecentViewedEvents = eventManager.GetMostRecentlyViewedEvents(5),
                EventTypes = eventManager.GetAllEventTypes()
            };

            return View("Events", model);
        }

        //
        // GET: /Event/Details/5

        public ActionResult Details(int id)
        {
            // Get Event
            Event evt = eventManager.GetEvent(id);
            
            // Update Event
            // evt.LastViewed = DateTime.UtcNow;
            // eventManager.UpdateEvent(evt, Utility.GetUserID(User.Identity.Name));

            // Calculate Relative Date
            ViewBag.RelativeDate = Utility.ToRelativeTime(evt.StartDate);
            ViewBag.Gravatar = Utility.MD5Hash(evt.Client.Email);

            return View("EventDetails", evt);
        }

        public ActionResult DetailsNew(int id)
        {
            // Get Event
            Event evt = eventManager.GetEvent(id);

            // Update Event
            evt.LastViewed = DateTime.UtcNow;
            eventManager.UpdateEvent(evt, Utility.GetUserID(User.Identity.Name));

            // Calculate Relative Date
            ViewBag.RelativeDate = Utility.ToRelativeTime(evt.StartDate);
            ViewBag.Gravatar = Utility.MD5Hash(evt.Client.Email);

            return View("EventDetailsNew", evt);
        }

        //
        // GET: /Event/Create

        public ActionResult Create()
        {
            return View("NewEvent", new Event_VM() { StartDate = DateTime.Now, EndDate = DateTime.Now.AddDays(1), StartTime = "5:00 PM", EndTime = "9:00 PM" });
        }

        //
        // POST: /Event/Create

        [HttpPost]
        public ActionResult Create(Event_VM model)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    DateTime startDate = DateTime.Parse(model.StartDate.ToShortDateString() + " " + model.StartTime);
                    DateTime endDate = DateTime.Parse(model.EndDate.ToShortDateString() + " " + model.EndTime);

                    if (DateTime.Compare(startDate, endDate) > -1)
                    {
                        throw new WeddingEventManagementException("Start Date must be before End Date", null);
                    }

                    int eventID = eventManager.CreateEvent
                        (
                            model.ClientID,
                            model.Title,
                            startDate,
                            endDate,
                            model.EventType,
                            model.PackageType.Value,
                            Utility.GetUserID(User.Identity.Name),
                            model.Notes,
                            model.Flowers,
                            model.FlowerBudget.HasValue ? model.FlowerBudget.Value : 0,
                            model.Decor,
                            model.DecorBudget.HasValue ? model.DecorBudget.Value : 0,
                            model.Coordination,
                            model.Guests.HasValue ? model.Guests.Value : 0
                        );
                    return RedirectToAction("Details", new { id = eventID });
                }

            }
            catch (WeddingEventManagementException ex)
            {
                ModelState.AddModelError("", ex.Message);
            }
            catch (FormatException)
            {
                ModelState.AddModelError("", "Must be a Valid Time");
            }
            catch (Exception ex)
            {
                ModelState.AddModelError("", ex.Message);
            }
            return View("NewEvent", model);
        }

        //
        // GET: /Event/Edit/5

        public ActionResult Edit(int id)
        {
            Event evt = eventManager.GetEvent(id);
            Client client = new ClientManager().GetClient(evt.ClientID);

            var model = new Event_VM
            {
                ClientID = evt.ClientID,
                ClientName = client.FirstName + " " + client.LastName,
                EndDate = evt.EndDate,
                EndTime = evt.EndDate.ToShortTimeString(),
                EventID = id,
                EventType = (EventTypeEnum)evt.EventTypeID,
                PackageType = (PackageType)evt.PackageID,
                StartDate = evt.StartDate,
                StartTime = evt.StartDate.ToShortTimeString(),
                Title = evt.Title
            };

            return View("EditEvent", model);
        }

        //
        // POST: /Event/Edit/5

        [HttpPost]
        public ActionResult Edit(int id, Event_VM model)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    DateTime startDate = DateTime.Parse(model.StartDate.ToShortDateString() + " " + model.StartTime);
                    DateTime endDate = DateTime.Parse(model.EndDate.ToShortDateString() + " " + model.EndTime);

                    //check if date is start is actually before the end date/time
                    if (DateTime.Compare(startDate, endDate) > -1)
                        throw new WeddingEventManagementException("Start Date must be before End Date", null);

                    Event e = eventManager.GetEvent(id);

                    e.ClientID = model.ClientID;
                    e.EndDate = endDate;
                    e.EventTypeID = (int)model.EventType;
                    e.PackageID = (int)model.PackageType;
                    e.StartDate = startDate;
                    e.Title = model.Title;
                    e.Package = null;
                    e.EventType = null;

                    eventManager.UpdateEvent(e, Utility.GetUserID(User.Identity.Name));

                    return RedirectToAction("Details", new { id = id });
                }

            }
            catch (WeddingEventManagementException ex)
            {
                ModelState.AddModelError("", ex.Message);
            }
            catch (FormatException)
            {
                ModelState.AddModelError("", "Must be a Valid Time");
            }
            return View("EditEvent", model);
        }

        //
        // POST: /Event/Delete/5

        [HttpPost]
        [HandleError]
        public ActionResult Delete(int id, FormCollection collection)
        {
            try
            {
                eventManager.DeleteEvent(id);
                return RedirectToAction("Index");
            }
            catch
            {
                ShowMessage("There was a problem deleting this event", MessageType.Error);
            }
            return RedirectToAction("Details", new { id = id });
        }

        public JsonResult GetLocationsJson()
        {
            // get clients filtered by search term
            var data = new LocationManager().GetLocations(null);

            // tranlate model to viewmodel
            var newlist = new List<AutoCompleteLocations_VM>();
            foreach (var location in data)
            {
                AutoCompleteLocations_VM loc = new AutoCompleteLocations_VM();
                loc.ID = location.LocationID;
                loc.Name = location.Name;
                newlist.Add(loc);
            }

            return Json(newlist, JsonRequestBehavior.AllowGet);
        }

        // Returns JSON Events for Calendar
        public JsonResult GetEvents(long start, long end)
        {
            var data = eventManager.GetEvents(start, end);
            var newlist = new List<Calendar_Entry>();

            // Map Model to ViewModel
            foreach (var evt in data)
            {
                Calendar_Entry c = new Calendar_Entry();
                c.id = evt.EventID;
                c.url = "/Event/Details/" + evt.EventID;
                c.start = Utility.ToUnixTimespan(evt.StartDate);
                c.end = Utility.ToUnixTimespan(evt.EndDate);
                c.title = evt.Title;
                c.allDay = false;
                c.className = evt.EventType.EventTypeName.Replace(" ", "") ?? "";
                c.color = evt.EventType.CalendarColor ?? "";

                newlist.Add(c);
            }

            return Json(newlist, JsonRequestBehavior.AllowGet);
        }

        // Returns the events in JSON form for AutoComplete
        public JsonResult Search(string term)
        {
            var data = new EventManager().GetEvents(term);

            var newlist = new List<AutoCompleteEvent_VM>();

            foreach (var evt in data)
            {
                AutoCompleteEvent_VM e = new AutoCompleteEvent_VM();
                e.ID = evt.EventID;
                e.Title = evt.Title;
                e.Color = evt.EventType.CalendarColor;
                e.Date = evt.StartDate.ToShortDateString();

                newlist.Add(e);
            }

            return Json(newlist, JsonRequestBehavior.AllowGet);
        }

        [HttpPost]
        public ActionResult NewLocation(int id, EventLocation_VM model)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    var evt = eventManager.GetEvent(id);
                    var locationManager = new LocationManager();
                    int location = locationManager.CreateLocation(model.Name, model.Address, model.City, model.PostalCode, (Province)model.Province, model.Lat, model.Lng, model.LocationType, 0, model.ContactName,
                        model.ContactPhone, model.ContactEmail, model.Notes, Utility.GetUserID(User.Identity.Name));

                    //DateTime startDate = DateTime.Parse(model.StartDate.ToShortDateString() + " " + model.StartTime);
                    DateTime time = DateTime.Parse(evt.StartDate.ToShortDateString() + " " + model.Time);
                    evt.EventLocations.Add(new EventLocation() { LocationID = location, LocationType = model.Type, Notes = model.Notes, EventID = model.EventID, Time = time });

                    eventManager.UpdateEvent(evt, Utility.GetUserID(User.Identity.Name));
                    return Redirect(Url.Action("Details", new {id = id}) + "#tab2");
                }
                catch (WeddingEventManagementException e)
                {
                    ModelState.AddModelError("", e.Message);
                }
            }

            return View(model);
        }

        public ActionResult NewLocation(int id)
        {
            var evt = eventManager.GetEvent(id);
            ViewBag.RelativeDate = Utility.ToRelativeTime(evt.StartDate);
            return View(new EventLocation_VM(){ EventID = id, e = evt, Time = evt.StartDate.ToShortTimeString() });
        }

        public ActionResult ExistingLocation(int id)
        {
            var evt = eventManager.GetEvent(id);
            ViewBag.RelativeDate = Utility.ToRelativeTime(evt.StartDate);
            return View(new ExistingEventLocation_VM() { EventID = id, e = evt, Time = evt.StartDate.ToShortTimeString() });
        }

        [HttpPost]
        public ActionResult ExistingLocation(int id, ExistingEventLocation_VM model)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    var evt = eventManager.GetEvent(id);

                    DateTime time = DateTime.Parse(evt.StartDate.ToShortDateString() + " " + model.Time);
                    evt.EventLocations.Add(new EventLocation() { LocationID =  model.LocationID, LocationType = model.Type, Notes = model.Notes, EventID = model.EventID, Time = time });

                    eventManager.UpdateEvent(evt, Utility.GetUserID(User.Identity.Name));
                    //return RedirectToAction("Details", new { id = id });
                    return Redirect(Url.Action("Details", new { id = id }) + "#tab2");
                }
                catch (FormatException)
                {
                    ModelState.AddModelError("", "Must be a Valid Time");
                }
                catch (WeddingEventManagementException e)
                {
                    ModelState.AddModelError("", e.Message);
                }
            }
            
            return View(model);
        }

        public ActionResult EditEventLocation(int evtID, int locID)
        {
            Event evt = eventManager.GetEvent(evtID);
            EventLocation evl = eventManager.GetEventLocation(evtID, locID);

            EditEventLocation_VM model = new EditEventLocation_VM 
            { 
                e = evt,
                el = evl,
                Time = evl.Time.Value.ToShortTimeString(),
                Type = evl.LocationType,
                Notes = evl.Notes,
                LocationID = locID,
                Date = evt.StartDate
            };
            ViewBag.RelativeDate = Utility.ToRelativeTime(evt.StartDate);
            return View("EditLocation", model);
        }

        [HttpPost]
        public ActionResult EditEventLocation(int evtID, int locID, EditEventLocation_VM model)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    DateTime time = DateTime.Parse(model.Date.ToShortDateString() + " " + model.Time);

                    EventLocation el = new EventLocation { 
                        EventID = evtID,
                        LocationID = locID,
                        LocationType = model.Type,
                        Notes = model.Notes,
                        Time = time 
                    };
                    eventManager.UpdateEventLocation(el, Utility.GetUserID(Membership.GetUser().UserName));

                    return RedirectToAction("Details", new { id = evtID });
                }

            }
            catch (WeddingEventManagementException ex)
            {
                ModelState.AddModelError("", ex.Message);
            }
            catch (FormatException)
            {
                ModelState.AddModelError("", "Must be a Valid Time");
            }
            return View("EditEvent", model);
        }

        public JsonResult UniqueLocationTypes()
        {
            ILocationManager loc = new LocationManager();
            return Json(loc.GetUniqueLocationTypes(), JsonRequestBehavior.AllowGet);
        }

        public JsonResult GetLocations()
        {
            ILocationManager loc = new LocationManager();
            var locations =  from location in loc.GetLocations(null) select new Location_DDL() { ID = location.LocationID, Name = location.Name};
            return Json(locations, JsonRequestBehavior.AllowGet);
        }

        // Get Event Types (JSON)
        public JsonResult GetAllEventTypesJson()
        {
            var eventTypes = from t in eventManager.GetAllEventTypes()
                             select new DropdownList_JSON()
                             {
                                 ID = t.EventTypeID,
                                 Name = t.EventTypeName
                             };

            return Json(eventTypes, JsonRequestBehavior.AllowGet);
        }

        // Get Packages
        public JsonResult GetPackagesJson()
        {
            var packages = from p in eventManager.GetAllPackages()
                             select new DropdownList_JSON()
                             {
                                 ID = p.PackageID,
                                 Name = p.PackageType + " - " + p.BasePrice.ToString("c")
                             };

            return Json(packages, JsonRequestBehavior.AllowGet);
        }

    }
}
